﻿using Halfpipe.Data.Repository;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Data.Objects;
using System.Data;
using System.Linq;
using Halfpipe.Test.Data;

namespace Halfpipe.Test
{    
    /// <summary>
    ///This is a test class for EntityRepositoryTest and is intended
    ///to contain all EntityRepositoryTest Unit Tests
    ///</summary>
    [TestClass]
    public class EntityRepositoryTest
    {
        [TestMethod]
        public void Delete_deletes()
        {
            using (var context = new NorthwindEntities())
            {
                var repository = new EntityRepository<Employee>(context);
                var expectedId = 123;
                var existingEntity = new Employee
                {
                    EmployeeID = expectedId
                };
                context.Employees.Attach(existingEntity);

                repository.Delete(new Employee { EmployeeID = expectedId });

                var stateEntries = context.ObjectStateManager.GetObjectStateEntries(EntityState.Deleted);
                var foundInContext = (from ose in stateEntries
                                      where ose.Entity is Employee
                                      select ose.Entity as Employee).Single();
                Assert.AreEqual(expectedId, foundInContext.EmployeeID);
            }
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void Delete_with_null_entity_argument_should_throw()
        {
            using (var context = new NorthwindEntities())
            {
                var repository = new EntityRepository<Employee>(context);
                var expectedId = 123;
                var existingEntity = new Employee
                {
                    EmployeeID = expectedId
                };
                context.Employees.Attach(existingEntity);

                repository.Delete(null);
            }
        }

        [TestMethod]
        public void Insert_adds_object_to_context()
        {
            using (var context = new NorthwindEntities())
            {
                var repository = new EntityRepository<Employee>(context);
                var expectedId = 123;
                var newEntity = new Employee
                {
                    EmployeeID = expectedId
                };

                var actual = repository.Insert(newEntity);

                var stateEntries = context.ObjectStateManager.GetObjectStateEntries(EntityState.Added);
                var foundInContext = (from ose in stateEntries
                                      where ose.Entity is Employee
                                      select ose.Entity as Employee).Single();
                Assert.AreEqual(expectedId, foundInContext.EmployeeID);
            }
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void Insert_with_null_entity_argument_should_throw()
        {
            using (var context = new NorthwindEntities())
            {
                var repository = new EntityRepository<Employee>(context);

                repository.Insert(null);
            }
        }

        [TestMethod]
        public void Update_alters_attached_object()
        {
            using (var context = new NorthwindEntities())
            {
                var repository = new EntityRepository<Employee>(context);
                var existingEntity = new Employee
                {
                    EmployeeID = 123,
                    FirstName = "Ralph"
                };
                context.Employees.Attach(existingEntity);
                var expected = "Bob";

                var editedEntity = new Employee
                {
                    EmployeeID = 123,
                    FirstName = expected
                };
                var actual = repository.Update(editedEntity);

                Assert.AreNotEqual(editedEntity, actual, "Update should return the existing entry.");
                Assert.AreEqual(existingEntity, actual, "Update should return the existing entry.");
                Assert.AreEqual(expected, actual.FirstName, "Failed to change the property value.");
            }
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void Update_with_null_entity_argument_should_throw()
        {
            using (var context = new NorthwindEntities())
            {
                var repository = new EntityRepository<Employee>(context);
                var expectedId = 123;
                var existingEntity = new Employee
                {
                    EmployeeID = expectedId
                };
                context.Employees.Attach(existingEntity);

                repository.Update(null);
            }
        }
    }
}
